using System;
using System.IO;
using System.Management;
using System.Messaging;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;

namespace CCSService_WebRole
{
	/// <summary>
	/// Currently defined product feature levels.  
	/// When adding a level here make sure to add the level to 
	/// GetCodedLicenseLevel in LicenseClient also. 
	/// </summary>
	//public enum LicenseLevels { Shareware, Premium };
    
	/// <summary>
	/// Implements the low-level manipulation of licenses, including
	/// creation, certification, and verification.
	/// </summary>
	[Serializable]
	public class License
	{
		public string ClientIdentity;
		public string LicenseLevel; //changed LicenseLevels to string
		public string Product;
		public byte [] AuthenticatedLicense;
		
		/// <summary>
		/// Default constructor
		/// </summary>
		public License()
		{
			
		}

		/// <summary>
		/// Determine the binding, identifying information for the data set 
		/// consisting of:  target workstation, product, license level 
		/// </summary>
		/// <param name="licenseLevel">Client license level</param>
		/// <param name="product">Product name string</param>
		/// <param name="clientIdentity">Unique client identity</param>
		protected void ComputeClientIdentity(
			string licenseLevel,
			string product,
			string clientIdentity)
		{


			UnicodeEncoding uniEncoding = new UnicodeEncoding();
            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
			byte[] clientInfoByteArray = uniEncoding.GetBytes(licenseLevel + product + clientIdentity);
			byte[] clientID = sha.ComputeHash(clientInfoByteArray);
			ClientIdentity = Convert.ToBase64String(sha.ComputeHash(clientInfoByteArray));
            sha.Clear();

			
			LicenseLevel = licenseLevel;
			Product = product;
		}

		/// <summary>
		/// Certify a license for the target client and product at the requested
		/// license level. 
		/// </summary>
		/// <param name="rsa">Provider handle to server private key</param>
		protected void CertifyLicense(RSACryptoServiceProvider rsa)
		{
            ComputeClientIdentity(LicenseLevel, Product, ClientIdentity);

			AuthenticatedLicense = rsa.SignHash(
                Convert.FromBase64String(ClientIdentity), 
				CryptoConfig.MapNameToOID("SHA1"));
		}

		/// <summary>
		/// Verify that this license is valid 
		/// </summary>
		/// <param name="serverPublicKey">Server public key</param>
		/// <returns>Authenticated license level</returns>
		protected String VerifyLicense(string serverPublicKey)
		{
			RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
			rsa.FromXmlString(serverPublicKey);

			if (false == rsa.VerifyHash(
				Convert.FromBase64String(ClientIdentity), 
				CryptoConfig.MapNameToOID("SHA1"), 
				AuthenticatedLicense))
			{
				throw new InvalidLicenseException("Product license validation failed");
			}

            rsa.Clear();
			
            return LicenseLevel;
		}
	}

	/// <summary>
	/// This class implements an exception which is thrown when an attempt is 
	/// made to verify an invalid license.
	/// </summary>
	public class InvalidLicenseException : Exception
	{
		//
		// Constructors
		//

		public InvalidLicenseException() {}
		public InvalidLicenseException(string s) : base(s) {}
		public InvalidLicenseException(string s, Exception innerE) 
			: base(s, innerE) {}
	}
}